﻿using System;
using System.Net;
using System.Web;
using System.Web.Security;
using Microsoft.ServiceModel.Web;
using Stimulus360.Repositories;
using Stimulus360.Services.Interfaces;
using Stimulus360.Repositories.Interfaces;
 

namespace Stimulus360.Services
{

    public class MembershipService : IMembershipService
    {
        /// <summary>
        ///     Instance of IMembership Repository to be used
        /// </summary>
        private readonly IMembershipRepository _memberRepository; 

        /// <summary>
        ///     Default constructor. Instantiates the default IMembership repository to be
        ///     used
        /// </summary>
        public MembershipService()
        {
            try
            {
                _memberRepository = new AspnetMembershipRepository();

            }
            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "One or more objects was null", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }

        }

        /// <summary>
        ///     Dependency Injection enabled constructor. Set the IMembership repository instance
        ///     to be used.
        /// </summary>
        /// <param name="memberRepository">
        ///     The IMembershipRepository instance to be used.
        /// </param>
        public MembershipService(IMembershipRepository memberRepository)
        {
            try
            {
                _memberRepository = memberRepository;

            }
            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "One or more objects was null", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     The allowed minimum length of the password
        /// </summary>
        public int MinPasswordLength
        {
            get
            {
                return _memberRepository.MinPasswordLength; 
            }
        }

        /// <summary>
        ///     Method to validate the user 
        /// </summary>
        /// <param name="userName">
        ///     Username provided for validation
        /// </param>
        /// <param name="password">
        ///     Password provided for validation
        /// </param>
        /// <returns>
        ///     Bool indicating if user is valid or not.
        /// </returns>
        public bool ValidateUser(string userName, string password)
        {
            try
            {
                userName = HttpUtility.HtmlEncode(userName);
                password = HttpUtility.HtmlEncode(password);
  

                return _memberRepository.ValidateUser(userName, password);

            }
            catch (ArgumentException exception)
            {
                throw new WebProtocolException(HttpStatusCode.BadRequest, "One or more arguments provided are invalid", exception);
            }

            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "One or more objects was null", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     Method to create a new user in the system
        /// </summary>
        /// <param name="userName">
        ///     The username provided by the user
        /// </param>
        /// <param name="password">
        ///     The Password provided by the user
        /// </param>
        /// <param name="email">
        ///     The email provided by the user
        /// </param>
        /// <returns>
        ///     Membership status.
        /// </returns>
        public MembershipCreateStatus CreateUser(string userName, string password, string email)
        {
            try
            {
                userName = HttpUtility.HtmlEncode(userName);
                password = HttpUtility.HtmlEncode(password);
                email = HttpUtility.HtmlEncode(email);

                return _memberRepository.CreateUser(userName, password, email);

            }
            catch (ArgumentException exception)
            {
                throw new WebProtocolException(HttpStatusCode.BadRequest, "One or more arguments provided are invalid", exception);
            }

            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "One or more objects was null", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     Method to allow the user change his password
        /// </summary>
        /// <param name="userName">
        ///     The Username
        /// </param>
        /// <param name="oldPassword">
        ///     The existing password
        /// </param>
        /// <param name="newPassword">
        ///     The new password
        /// </param>
        /// <returns>
        ///     Bool indicating if password was successfully changed
        /// </returns>
        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            try
            {
                userName = HttpUtility.HtmlEncode(userName);
                oldPassword = HttpUtility.HtmlEncode(oldPassword);
                newPassword = HttpUtility.HtmlEncode(newPassword);

                return _memberRepository.ChangePassword(userName, oldPassword, newPassword);

            }
            catch (ArgumentException exception)
            {
                throw new WebProtocolException(HttpStatusCode.BadRequest, "One or more arguments provided are invalid", exception);
            }

            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "One or more objects was null", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }

        /// <summary>
        ///     Method to check if a username already exists
        /// </summary>
        /// <param name="userName">
        ///     The username to check
        /// </param>
        /// <returns>
        ///     Bool indicating if the username is already in use.
        /// </returns>
        public bool UserExists(string userName)
        {
            try
            {
                userName = HttpUtility.HtmlEncode(userName);

                return _memberRepository.UserExists(userName);

            }
            catch (ArgumentException exception)
            {
                throw new WebProtocolException(HttpStatusCode.BadRequest, "User Name provided is invalid", exception);
            }

            catch (NullReferenceException exception)
            {
                throw new WebProtocolException(HttpStatusCode.InternalServerError, "One or more objects was null", exception);
            }
            catch (Exception exception)
            {
                throw new WebProtocolException(ExceptionHelper.GetStatusCode(exception), exception.Message, exception);
            }
        }


    }
}
